#pragma once

#include <memory>
#include <list>

namespace cyb
{

struct MouseButton
{
	enum Enum
	{
		None,
		Left,
		Middle,
		Right,
		Count
	};
};

struct KeyCode
{
	enum Enum
	{
		None = 0,
		Esc,
		Return,
		Tab,
		Space,
		Backspace,
		Up,
		Down,
		Left,
		Right,
		PageUp,
		PageDown,
		Home,
		End,
		Print,
		Plus,
		Minus,
		F1,
		F2,
		F3,
		F4,
		F5,
		F6,
		F7,
		F8,
		F9,
		F10,
		F11,
		F12,
		NumPad0,
		NumPad1,
		NumPad2,
		NumPad3,
		NumPad4,
		NumPad5,
		NumPad6,
		NumPad7,
		NumPad8,
		NumPad9,
		Key0,
		Key1,
		Key2,
		Key3,
		Key4,
		Key5,
		Key6,
		Key7,
		Key8,
		Key9,
		KeyA,
		KeyB,
		KeyC,
		KeyD,
		KeyE,
		KeyF,
		KeyG,
		KeyH,
		KeyI,
		KeyJ,
		KeyK,
		KeyL,
		KeyM,
		KeyN,
		KeyO,
		KeyP,
		KeyQ,
		KeyR,
		KeyS,
		KeyT,
		KeyU,
		KeyV,
		KeyW,
		KeyX,
		KeyY,	
		KeyZ,
		Count
	};
};

struct KeyModifier
{
	enum Enum
	{
		None		= 0x00,
		LeftAlt		= 0x01,
		RightAlt	= 0x02,
		LeftCtrl	= 0x04,
		RightCtrl	= 0x08,
		LeftShift	= 0x10,
		RightShift	= 0x20,
		LeftMeta	= 0x40,
		RightMeta	= 0x80
	};
};

class IKeyboardListener
{
public:
	virtual bool OnKeyDown( const char c ) = 0;
	virtual bool OnKeyUp( const char c ) = 0;
};

class IMouseListener
{
public:
	virtual bool OnMouseMove( int32_t x, int32_t y ) = 0;
	virtual bool OnMouseButtonDown( int32_t x, int32_t y, MouseButton::Enum button ) = 0;
	virtual bool OnMouseButtonUp( int32_t x, int32_t y, MouseButton::Enum button ) = 0;
};

class InputListener
{
public:
	InputListener( std::shared_ptr<IKeyboardListener> keyboard, std::shared_ptr<IMouseListener> mouse ) :
		keyboardListener( keyboard ),
		mouseListener( mouse ) {}
	std::shared_ptr<IKeyboardListener> keyboardListener;
	std::shared_ptr<IMouseListener> mouseListener;
};

using InputListenerList = std::list<std::shared_ptr<InputListener>>;

}	// namespace cyb